/*-
 * $Id: SwingUi.java 4 2010-11-04 07:39:56Z andrewbass $
 */

package com.google.code.getwrong;

import static java.awt.BorderLayout.CENTER;
import static java.awt.BorderLayout.NORTH;
import static java.awt.BorderLayout.SOUTH;
import static java.text.MessageFormat.format;
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

/**
 * @author Andrew ``Bass'' Shcheglov (andrewbass@gmail.com)
 * @author $Author: andrewbass $
 * @version $Revision: 4 $, $Date:: 2010-11-04 07:39:56 +0000 #$
 * @todo 3 progress-bars (file, bytes, count like in MC).
 */
final class SwingUi implements Ui {
	final JProgressBar progressBar = new JProgressBar();

	final JTextArea textArea = new JTextArea();

	final JButton button = new JButton();

	SwingUi() {
		// empty
	}

	/**
	 * @see Ui#init()
	 */
	@Override
	public void init() {
		try {
			SwingUtilities.invokeAndWait(new Runnable() {
				/**
				 * @see Runnable#run()
				 */
				@Override
				public void run() {
					SwingUi.this.progressBar.setMinimum(0);
					SwingUi.this.progressBar.setStringPainted(true);

					SwingUi.this.textArea.setEditable(false);

					final JScrollPane scrollPane = new JScrollPane();
					scrollPane.getViewport().add(SwingUi.this.textArea);

					SwingUi.this.button.setEnabled(false);
					SwingUi.this.button.setText("Exit");
					SwingUi.this.button.addActionListener(new ActionListener(){
						/**
						 * @see ActionListener#actionPerformed(ActionEvent)
						 */
						@Override
						public void actionPerformed(final ActionEvent e) {
							System.exit(0);
						}
					});

					final BorderLayout layout = new BorderLayout();
					layout.setHgap(5);
					layout.setVgap(5);

					final JPanel panel = new JPanel();
					panel.setLayout(layout);
					panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
					panel.add(SwingUi.this.progressBar, NORTH);
					panel.add(scrollPane, CENTER);
					panel.add(SwingUi.this.button, SOUTH);

					final JFrame frame = new JFrame(Main.class.getName());
					frame.setContentPane(panel);
					frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

					//*/
					frame.setPreferredSize(new Dimension(640, 480));
					frame.pack();
					/*/
					frame.setSize(new Dimension(640, 480));
					frame.validate();
					//*/

					frame.setVisible(true);
				}
			});
		} catch (final InterruptedException ie) {
			/*
			 * In case anyone relies on it, restore current thread's
			 * interrupted status. 
			 */
			Thread.currentThread().interrupt();
		} catch (final InvocationTargetException ite) {
			/*-
			 * Never.
			 */
			throw new Error(ite.getCause());
		}
	}

	/**
	 * @see Ui#usage()
	 */
	@Override
	public void usage() {
		JOptionPane.showMessageDialog(null, format("Usage: {0} [FILE...]", Main.class.getName()));
	}

	/**
	 * @see Ui#println(String)
	 */
	@Override
	public void println(final String message) {
		try {
			SwingUtilities.invokeAndWait(new Runnable() {
				/**
				 * @see Runnable#run()
				 */
				@Override
				public void run() {
					SwingUi.this.textArea.append(message);
					SwingUi.this.textArea.append(System.getProperty("line.separator"));
				}
			});
		} catch (final InterruptedException ie) {
			/*
			 * In case anyone relies on it, restore current thread's
			 * interrupted status. 
			 */
			Thread.currentThread().interrupt();
		} catch (final InvocationTargetException ite) {
			/*-
			 * Never.
			 */
			throw new Error(ite.getCause());
		}
	}

	/**
	 * @see Ui#println(String, Object[])
	 */
	@Override
	public void println(final String pattern, final Object ... arguments) {
		SwingUi.this.println(format(pattern, arguments));
	}

	/**
	 * @see Ui#setProgressValue(long)
	 * @todo add the fix for large numbers
	 */
	@Override
	public long setProgressValue(final long n) {
		try {
			SwingUtilities.invokeAndWait(new Runnable() {
				/**
				 * @see Runnable#run()
				 */
				@Override
				public void run() {
					SwingUi.this.progressBar.setValue(n <= Integer.MAX_VALUE ? (int) n : Integer.MAX_VALUE);
				}
			});
		} catch (final InterruptedException ie) {
			/*
			 * In case anyone relies on it, restore current thread's
			 * interrupted status. 
			 */
			Thread.currentThread().interrupt();
		} catch (final InvocationTargetException ite) {
			/*-
			 * Never.
			 */
			throw new Error(ite.getCause());
		}
		return n;
	}

	/**
	 * @see Ui#setProgressMaximum(long)
	 * @todo add the fix for large numbers
	 */
	@Override
	public void setProgressMaximum(final long n) {
		try {
			SwingUtilities.invokeAndWait(new Runnable() {
				/**
				 * @see Runnable#run()
				 */
				@Override
				public void run() {
					SwingUi.this.progressBar.setMaximum(n <= Integer.MAX_VALUE ? (int) n : Integer.MAX_VALUE);
				}
			});
		} catch (final InterruptedException ie) {
			/*
			 * In case anyone relies on it, restore current thread's
			 * interrupted status. 
			 */
			Thread.currentThread().interrupt();
		} catch (final InvocationTargetException ite) {
			/*-
			 * Never.
			 */
			throw new Error(ite.getCause());
		}
	}

	/**
	 * @see Ui#enableExit()
	 */
	@Override
	public void enableExit() {
		SwingUtilities.invokeLater(new Runnable() {
			/**
			 * @see Runnable#run()
			 */
			@Override
			public void run() {
				SwingUi.this.button.setEnabled(true);
			}
		});
	}
}
